﻿using System;
using System.Collections.Generic;
using Com.OpenCode.Framework.Core;

namespace Com.OpenCode.Framework.Workbench
{
    /// <summary>
    ///     UI插件信息解析。
    /// </summary>
    public class WorkbenchPlugin
    {
        public WorkbenchPlugin(Addins addins)
        {
            List<Plugin> plugins = new List<Plugin>();
            for (int i = 0; i < addins.Count; i++)
            {
                Addin addin = addins.Get(i);
                Plugin plugin = addin.Plugin.Search("MainForm");
                if (plugin != null)
                {
                    plugins.AddRange(plugin.ToList(null));
                }
            }
            if (plugins.Count == 0)
            {
                return;
            }
            Plugin = plugins[0];
            for (int i = 1; i < plugins.Count; i++)
            {
                Plugin plugin = plugins[i];
                int j = i;
                while ((j > 0) && Compare(plugins[j - 1], plugin, true) < 0)
                {
                    plugins[j] = plugins[j - 1];
                    --j;
                }
                plugins[j] = plugin;
            }
            //合并插件。
            foreach (var plugin in plugins)
            {
                Merge(plugin, Plugin);
            }
            Plugin.Sort(new PluginComparer());
        }

        public Plugin Plugin { get; private set; }

        private void Merge(Plugin souPlugin, Plugin targetPlugin)
        {
            string southPath = souPlugin.Properties.Get("Path").ToString();
            string targetPath = targetPlugin.Properties.Get("Path").ToString();
            if (southPath.Equals(targetPath)) return;
            if (!StartWith(southPath, targetPath)) return;
            if (targetPlugin.Children.Count == 0)
            {
                targetPlugin.Children.Add(souPlugin);
            }
            else
            {
                Plugin plugin = Search(targetPlugin, southPath);
                if (plugin == null)
                {
                    targetPlugin.Children.Add(souPlugin);
                }
                else
                {
                    Merge(souPlugin, plugin);
                }
            }
        }

        private Plugin Search(Plugin targetPlugin, string southPath)
        {
            foreach (var plugin in targetPlugin.Children)
            {
                object path = plugin.Properties.Get("Path");
                if (StartWith(southPath, path.ToString())) return plugin;
            }
            return null;
        }

        private int Compare(Plugin southPlugin, Plugin tarPlugin, bool sortBy)
        {
            string souPath = string.Empty;
            string tarPath = string.Empty;
            if (!string.IsNullOrEmpty(southPlugin.Properties.Get("Path").ToString()))
            {
                souPath = southPlugin.Properties.Get("Path").ToString();
            }
            if (!string.IsNullOrEmpty(tarPlugin.Properties.Get("Path").ToString()))
            {
                tarPath = tarPlugin.Properties.Get("Path").ToString();
            }
            if (sortBy)
            {
                return string.Compare(tarPath, souPath, StringComparison.Ordinal);
            }
            return string.Compare(souPath, tarPath, StringComparison.Ordinal);
        }

        private bool StartWith(string southPath, string targetPath)
        {
            if (!southPath.StartsWith(targetPath)) return false;
            string[] southNodes = southPath.Split(Convert.ToChar("/"));
            string[] targetNodes = targetPath.Split(Convert.ToChar("/"));
            for (int index = 0; index < targetNodes.Length; index++)
            {
                string targetNode = targetNodes[index];
                string southNode = southNodes[index];
                if (string.IsNullOrEmpty(targetNode))
                    continue;
                if (targetNode == southNode)
                    continue;
                return false;
            }
            return true;
        }
    }
}